package com.stars.easyms.redis.interceptor;

import com.stars.easyms.base.util.GenericTypeUtil;
import com.stars.easyms.base.util.ReflectUtil;
import com.stars.easyms.redis.annotion.RedisSetMembers;
import com.stars.easyms.redis.exception.RedisInterceptorException;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.util.CollectionUtils;

import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * <p>className: RedisListRangeInterceptor</p>
 * <p>description: RedisListRange注解拦截器</p>
 *
 * @author jinzhilong
 * @date 2019-12-24 17:44
 */
public class RedisSetMembersInterceptor extends AbstractRedisInterceptor<RedisSetMembers> {

    @Override
    Object invoke(MethodInvocation methodInvocation, RedisSetMembers redisSetMembers) throws RedisInterceptorException {
        Object result = null;
        if (isEnabled()) {
            Method pointMethod = methodInvocation.getMethod();
            Class<?> returnType = pointMethod.getReturnType();
            boolean isInvalidReturnType = !List.class.isAssignableFrom(returnType) && !Set.class.isAssignableFrom(returnType);
            if (isInvalidReturnType) {
                logger.error("Method '{}' returnType should be List<T> or Set<T>!", ReflectUtil.getMethodFullName(pointMethod));
                return proceed(methodInvocation);
            }

            String redisKey = getRedisKey(methodInvocation, redisSetMembers.group());
            Type genericReturnType = pointMethod.getGenericReturnType();
            if (!(genericReturnType instanceof ParameterizedType)) {
                result = easyMsRedisTemplate.setMembers(redisKey);
            } else {
                Class<?> clazz = GenericTypeUtil.getGenericClass(genericReturnType, 0);
                result = easyMsRedisTemplate.setMembers(redisKey, clazz);
            }
            if (!CollectionUtils.isEmpty((Set<?>) result)) {
                Long expire = getExpire(methodInvocation, redisSetMembers.expire());
                boolean isSetExpire = expire != null && expire > 0 && easyMsRedisTemplate.getExpire(redisKey, TimeUnit.MILLISECONDS) <= 0;
                if (isSetExpire) {
                    easyMsRedisTemplate.expire(redisKey, expire, TimeUnit.MILLISECONDS);
                }
                // 返回类型为List时候 进行转化
                if (List.class.isAssignableFrom(returnType)) {
                    result = new ArrayList<>((Set<?>) result);
                }
                return result;
            }
            result = proceed(methodInvocation);
            if ((!CollectionUtils.isEmpty((Collection<?>) result))) {
                easyMsRedisTemplate.setAdd(redisKey, (Collection<?>) result);
                Long expire = getExpire(methodInvocation, redisSetMembers.expire());
                if (expire != null && expire > 0) {
                    easyMsRedisTemplate.expire(redisKey, expire, TimeUnit.MILLISECONDS);
                }
            }
        }
        return result;
    }
}